package com.test.weixin.service;

import com.alibaba.fastjson.JSON;
import com.test.weixin.constant.WxConstant;
import com.test.weixin.util.WxHttpUtil;
import com.test.weixin.util.WxSignUtil;
import com.test.weixin.util.WxXmlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 支付学习 参考：https://my.oschina.net/wangnian/blog/757140
 * Created by Administrator on 2019/2/13.
 * 微信支付： 规则参考 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_2
 * 传输方式	采用HTTPS传输
 * 提交方式	采用POST方法提交
 * 数据格式	提交和返回数据都为XML格式，根节点名为xml
 * 字符编码	统一采用UTF-8字符编码
 * 签名算法	MD5
 * 签名要求	请求和接收数据均需要校验签名\
 * 证书要求	调用申请退款、撤销订单接口需要商户证书
 * 判断逻辑	先判断协议字段返回，再判断业务返回，最后判断交易状态
 * <p>
 * 交易金额默认为 人民币交易 ，接口中参数支付金额单位为【分】，参数值不能带小数.
 * 交易类型(trade_type)  JSAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付、MWEB--H5支付、MICROPAY--付款码支付(单独的支付接口)
 * 时间  需为标准北京时间，时区为东八区
 * 时间戳  标准北京时间，时区为东八区，自1970年1月1日 0点0分0秒以来的秒数。注意：部分系统取到的值为毫秒级，需要转换成秒(10位数字)。
 * 商户支付的订单号由商户自定义生成，仅支持使用字母、数字、中划线-、下划线_、竖线|、星号*这些英文半角字符的组合。微信支付要求商户订单号保持唯一性（建议根据当前系统时间加随机序列来生成订单号）。
 * 重新发起一笔支付要使用原订单号，避免重复支付；已支付过或已调用关单、撤销（请见后文的API列表）的订单号不能重新发起支付。
 */
public class WxPayService {
    private static final Logger logger = LoggerFactory.getLogger(WxPayService.class);

    /**
     * 统一下单接口
     * 商户系统先调用该接口在微信支付服务后台生成预支付交易单，返回正确的预支付交易会话标识后再在APP里面调起支付。
     * 接口链接 https://api.mch.weixin.qq.com/pay/unifiedorder
     * 不需要证书
     *
     * @param parameters  请求参数 Map
     * @return  Map( app端调起支付所需参数)
     */
    public static Map<String, String> sendWxPayRequest(SortedMap<String, String> parameters) {
        // 随机字符串-用于保证签名 不可预测
        if (parameters.get("nonce_str") == null) {
            parameters.put("nonce_str", WxSignUtil.createNonceStr());
        }
        // 生成 签名
        String sign = WxSignUtil.createSign(parameters);
        parameters.put("sign", sign);
        // 生成签名后，移除密钥
        parameters.remove("key");
        // 生成xml
        String requestXmlStr = WxXmlUtil.mapToXmlStr(parameters);
        // 调用接口进行post请求
        String resultStr = WxHttpUtil.doPost(WxConstant.WX_PAY_URL, requestXmlStr);
        // 将返回结果转换为Map
        SortedMap<String, String> resultMap = WxXmlUtil.xmlStrToMap(resultStr);
        if (WxConstant.SUCCESS.equals(resultMap.get("return_code"))) {
            logger.warn("订单 " + parameters.get("out_trade_no") + " 微信统一下单成功:{}", JSON.toJSON(resultMap));
        } else {
            logger.warn("订单 " + parameters.get("out_trade_no") + " 微信统一下单出错:{}", JSON.toJSON(resultMap));
        }
        // 统一下单接口成功后  ，返回 app端调用 调起支付接口 所需参数
        SortedMap<String, String> transferPaymentMap =new TreeMap<String, String>();
        //统一下单成功返回的  预支付交易会话标识
        transferPaymentMap.put("prepayid",resultMap.get("prepay_id"));
        transferPaymentMap.put("package", "Sign=WXPay"); //扩展字段 固定值
        transferPaymentMap.put("appid",parameters.get("appid")); // 商户唯一标识
        transferPaymentMap.put("partnerid",parameters.get("mch_id"));// 商户收款账号
        transferPaymentMap.put("noncestr", WxSignUtil.createNonceStr() ); // 随机字符串
        transferPaymentMap.put("timestamp",""+(System.currentTimeMillis()/1000) ); // unix时间戳
        transferPaymentMap.put("sign",WxSignUtil.createSign(transferPaymentMap)); // 签名
        return transferPaymentMap;
    }
}
